# @Version : 1.0
# @Author  : wxz
# @File    : main.py
# @Time    : 2025/6/1 15:49
# @Describe: 描述...
import os
from contextlib import asynccontextmanager
from typing import AsyncGenerator

import uvicorn
from fastapi import FastAPI, Depends
from fastapi.exceptions import RequestValidationError
from starlette.exceptions import HTTPException
from fastapi.middleware.cors import CORSMiddleware

from apps.docs_auth.routers.docs_routers import docs
from apps.home.routers.home import home
from apps.user.routers.user_router import users
from commons.exception_handler import global_exception_handler, validation_exception_handler, buzz_exception_handler, \
    BaseAPIException
from config import app_settings
from config.app_logger import logger
from config.uvicorn_log_config import UvicornLoggerWrapper
from middlewares.access_token_middleware import AccessTokenMiddleware
from utils.oauth2 import OAuth2

# 异常处理器
my_exception_handlers = {
    # 处理HTTP请求错误
    HTTPException: global_exception_handler,
    # 处理请求参数错误
    RequestValidationError: validation_exception_handler,
    # 处理自定业务系统异常
    BaseAPIException: buzz_exception_handler,
}

@asynccontextmanager
async def lifespan(app: FastAPI) -> AsyncGenerator:
    """
    解释说明
    @asynccontextmanager 是一个装饰器，用于创建异步上下文管理器。
    lifespan 是一个函数，返回一个异步生成器（AsyncGenerator）。
    在 yield 之前的部分是 启动时运行的代码 。
    在 yield 之后的部分是 关闭时运行的代码 。
    lifespan=lifespan 被传入 FastAPI 实例中，代替旧的 on_event 方式。
    """

    # 应用启动时执行的代码
    logger.info("🚀 应用正在启动，初始化资源...")

    yield  # 控制权交给 FastAPI 主程序

    # 应用关闭时执行的代码
    logger.info("🛑 应用正在关闭，释放资源...")

# 添加自定义的接口文档OAuth2实现
oauth2 = OAuth2(tokenUrl="/docs/token", schema="JWT")

# exception_handlers : 异常处理器
# dependencies : 全局依赖 依赖项->oauth2
app = FastAPI(
    exception_handlers=my_exception_handlers,
    dependencies=[Depends(oauth2)],
    lifespan=lifespan,
)

# 注册中间件
# 第一个中间件: 跨域请求
app.add_middleware(
    CORSMiddleware, # type: ignore
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# 第二个中间件: Token令牌校验
app.add_middleware(AccessTokenMiddleware) # type: ignore

# 添加日志中间件
app.middleware("http")(logger.get_fastapi_middleware())

# 注册路由
# home
app.include_router(home, tags=["Home"])
app.include_router(docs, prefix="/docs", tags=["docs文档Token认证"])

app.include_router(users, prefix="/user", tags=["用户管理"])


# Create the wrapper
uvicorn_logger = UvicornLoggerWrapper(logger)
# Configure Uvicorn to use your logging system
uvicorn_logger.intercept_uvicorn_logs(logger)

# 启动
if __name__ == '__main__':
    uvicorn.run(
        app,
        host=app_settings.server.host,
        port=app_settings.server.port,
        log_config=uvicorn_logger.get_uvicorn_log_config(),
    )



